#include "user.h"
DMA_CtrlStruct DMACtrl[DMA_CHANNEL_MAX];
//#define DBG_DMA	DBG
#define DBG_DMA(X, Y...)
void DMA1_Channel1_IRQHandler(void)
{
	uint32_t SR = DMA1->ISR;
	PV_Union Flag;
	MyCBFun_t Fun;
	LL_DMA_ClearFlag_GI1(DMA1);
	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF1)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_1 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF1)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF1)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_1 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_1].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_1].CB;
			DMACtrl[DMA_CHANNEL_1].CB = NULL;
			Fun(Flag);
		}
	}
}

void DMA1_Channel2_3_IRQHandler(void)
{
	uint32_t SR = DMA1->ISR;
	PV_Union Flag;
	MyCBFun_t Fun;
	LL_DMA_ClearFlag_GI2(DMA1);
	LL_DMA_ClearFlag_GI3(DMA1);
	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF2)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_2 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF2)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF2)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_2 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_2].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_2].CB;
			DMACtrl[DMA_CHANNEL_2].CB = NULL;
			Fun(Flag);
		}
	}

	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF3)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_3 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF3)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF3)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_3 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_3].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_3].CB;
			DMACtrl[DMA_CHANNEL_3].CB = NULL;
			Fun(Flag);
		}
	}
}

#if (defined STM32F0)
void DMA1_Channel4_5_IRQHandler(void)
{
	uint32_t SR = DMA1->ISR;
	PV_Union Flag;
	MyCBFun_t Fun;
	LL_DMA_ClearFlag_GI4(DMA1);
	LL_DMA_ClearFlag_GI5(DMA1);
	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF4)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_4 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF4)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF4)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_4 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_4].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_4].CB;
			DMACtrl[DMA_CHANNEL_4].CB = NULL;
			Fun(Flag);
		}
	}

	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF5)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_5 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF5)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF5)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_5 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_5].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_5].CB;
			DMACtrl[DMA_CHANNEL_5].CB = NULL;
			Fun(Flag);
		}
	}
}
#endif

#if (defined STM32L0)
void DMA1_Channel4_5_6_7_IRQHandler(void)
{
	uint32_t SR = DMA1->ISR;
	PV_Union Flag;
	MyCBFun_t Fun;
	LL_DMA_ClearFlag_GI4(DMA1);
	LL_DMA_ClearFlag_GI5(DMA1);
	LL_DMA_ClearFlag_GI6(DMA1);
	LL_DMA_ClearFlag_GI7(DMA1);
	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF4)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_4 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF4)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF4)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_4 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_4].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_4].CB;
			DMACtrl[DMA_CHANNEL_4].CB = NULL;
			Fun(Flag);
		}
	}

	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF5)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_5 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF5)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF5)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_5 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_5].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_5].CB;
			DMACtrl[DMA_CHANNEL_5].CB = NULL;
			Fun(Flag);
		}
	}

	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF6)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_6 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF6)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF6)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_6 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_6].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_6].CB;
			DMACtrl[DMA_CHANNEL_6].CB = NULL;
			Fun(Flag);
		}
	}

	Flag.u32 = 0;

	if (SR & DMA_IFCR_CTCIF7)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_7 + 1);
		Flag.u32 = DMA_DONE;
	}
	else if (SR & DMA_IFCR_CHTIF7)
	{
		Flag.u32 = DMA_HALF_DONE;
	}
	else if (SR & DMA_IFCR_CTEIF7)
	{
		//LL_DMA_DisableChannel(DMA1, DMA_CHANNEL_7 + 1);
		Flag.u32 = DMA_ERROR;
	}
	if (Flag.u32)
	{
		if (DMACtrl[DMA_CHANNEL_7].CB)
		{
			Fun = DMACtrl[DMA_CHANNEL_7].CB;
			DMACtrl[DMA_CHANNEL_7].CB = NULL;
			Fun(Flag);
		}
	}
}
#endif


uint32_t DMA_Start(uint8_t Channel, uint32_t Config, MyCBFun_t CB, uint32_t DevAddr, uint32_t MemAddr, uint16_t Len)
{
	switch (Channel)
	{
	case DMA_CHANNEL_1:
		LL_DMA_ClearFlag_GI1(DMA1);
		break;
	case DMA_CHANNEL_2:
		LL_DMA_ClearFlag_GI2(DMA1);
		break;
	case DMA_CHANNEL_3:
		LL_DMA_ClearFlag_GI3(DMA1);
		break;
	case DMA_CHANNEL_4:
		LL_DMA_ClearFlag_GI4(DMA1);
		break;
	case DMA_CHANNEL_5:
		LL_DMA_ClearFlag_GI5(DMA1);
		break;
#if (defined STM32F0)
#else
	case DMA_CHANNEL_6:
		LL_DMA_ClearFlag_GI6(DMA1);
		break;
	case DMA_CHANNEL_7:
		LL_DMA_ClearFlag_GI7(DMA1);
		break;
#endif
	default:
		return 0;
	}

	LL_DMA_DisableChannel(DMA1, Channel + 1);
	LL_DMA_ConfigTransfer(DMA1, Channel + 1, Config);
	LL_DMA_SetMemoryAddress(DMA1, Channel + 1, MemAddr);
	LL_DMA_SetPeriphAddress(DMA1, Channel + 1, DevAddr);
	LL_DMA_SetDataLength(DMA1, Channel + 1, Len);
	if (CB)
	{
		LL_DMA_EnableIT_TC(DMA1, Channel + 1);
		LL_DMA_EnableIT_TE(DMA1, Channel + 1);
		DMACtrl[Channel].CB = CB;
	}
	else
	{
		LL_DMA_DisableIT_TC(DMA1, Channel + 1);
		LL_DMA_DisableIT_TE(DMA1, Channel + 1);
		DMACtrl[Channel].CB = NULL;
	}
	LL_DMA_EnableChannel(DMA1, Channel + 1);
	return LL_DMA_IsEnabledChannel(DMA1, Channel + 1);
}

void DMA_Stop(uint8_t Channel)
{
	LL_DMA_DisableChannel(DMA1, Channel + 1);
}

uint32_t DMA_GetSize(uint8_t Channel)
{
	return LL_DMA_GetDataLength(DMA1, Channel);
}

uint32_t DMA_Busy(uint8_t Channel)
{
	return LL_DMA_IsEnabledChannel(DMA1, Channel + 1);
}
